package com.hyxt.DTO;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hyxt.dao.RedisServiceDAO;
import com.hyxt.utils.T809_Util;
import com.hyxt.utils.bytes.BytesUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;



import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * @author shenp
 * @version v1.0
 * @Description T809客户端链路管理类
 * @Date: Create in 10:54 2017/11/23
 * @Modifide By:
 **/
public class T809ClientHandler extends ChannelInboundHandlerAdapter{
    /**
     * 主从标识
     */
    private Integer mainOrBranch;
    /**
     * 唯一标识 平台接入码
     */
    private Integer sign;
    /**
     * 客户端ip
     */
    private String ip;
    /**
     * 客户端端口
     */
    private Integer port;
    /**
     * 接受转发标识
     */
    private Integer accessOrForward;
    /**
     * T809拆解包对象
     */
    private T809Case t809Case=new T809Case() ;
    /**
     * 输入数据缓存
     */
    private ByteBuf in = Unpooled.buffer();
    /**
     * 链路缓存
     */
    public final static Map<String,Channel> channelMap = new HashMap<String,Channel>();

    /**
     * redis接口
     */
    RedisServiceDAO redisServiceDAO;



    public T809ClientHandler(Integer mainOrBranch, Integer sign,RedisServiceDAO redisServiceDAO,Integer accessOrForward){
        this.mainOrBranch = mainOrBranch;
        this.sign = sign;
        this.redisServiceDAO = redisServiceDAO;
        this.accessOrForward = accessOrForward;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //原始数据
        byte[] bytes = (byte[]) msg;
        //byte[] bytes = BytesUtil.toStringHex("5b0000001f0032a63a10020225510102010f0055d5ae1100000004d2232e5d");
        //数据完整性
        in.writeBytes(bytes);
        byte[] datas =  t809Case.disassemblyByByteBuf(in);
        if(datas==null){
            return;
        }
        //反转义
        byte[] reverseBytes = T809_Util.reverseEscapeData(bytes);
        //CRC校验
        // 用校验方法算出的crc校验码
        short checkCode = BytesUtil.parseBytesToShort(T809_Util.check(reverseBytes));
        // 数据体携带的crc校验码
        short crcCode = BytesUtil.parseBytesToShort(BytesUtil.cutBytes(reverseBytes.length - 3, 2, reverseBytes));
        // 判断crc校验码是否正确
        boolean check = checkCode == crcCode;
        if (check){
            if (sign==null){
//                byte[] gnsscenteridData = BytesUtil.getDWord(11, reverseBytes);
//                // 截取接入码
//                sign = BytesUtil.parseBytesToInt(gnsscenteridData);

            }
            //发送到redis通道
                JSONObject json =new JSONObject();
                json.put("ip",ip);
                json.put("port",port);
                json.put("mainOrBranch",mainOrBranch);
                json.put("datas",new String(reverseBytes));
                if(accessOrForward==0){
                    redisServiceDAO.sendMessage("T809AccessMessage", JSON.toJSONString(json));
                }else if(accessOrForward==1){
                    redisServiceDAO.sendMessage("T809ForwardMessage", JSON.toJSONString(json));
                }
        }
    }

    /**
     * 链路建立触发事件
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //获取客户端的ip和端口
        InetSocketAddress ipPort = (InetSocketAddress) ctx.channel().localAddress();
        ip = ipPort.getAddress().toString().substring(1);
        port = ipPort.getPort();
        //链路存入缓存中
        channelMap.put(ip+"-"+port+"-"+mainOrBranch,ctx.channel());
        //唯一标识与链路的对应关系存入redis中
        HashMap<String,String> signMap = new HashMap<String, String>();
        signMap.put("position","client");
        signMap.put("ip",ip+"-"+port+"-"+mainOrBranch);
        //唯一标识与链路的关系存储到redis
        redisServiceDAO.setMap(sign+mainOrBranch+"",signMap,0);
    }

    /**
     * 链路断开触发事件
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //移除链路
        channelMap.remove(ip+"-"+port+"-"+mainOrBranch,ctx.channel());
        //移除redis中的对应关系
        redisServiceDAO.delete(sign+mainOrBranch+"",0);
    }

    /**
     * 链路异常触发事件
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        //移除链路
        channelMap.remove(ip+"-"+port+"-"+mainOrBranch,ctx.channel());
        //移除redis中的对应关系
        redisServiceDAO.delete(sign+mainOrBranch+"",0);
    }
}
